// 菜单模块，将请求后端所获取的菜单列表保存到Vuex里当前menu模块中
// 将src/api/menu.js中的getMenuList方法导入进来
import { getMenuList } from '@/api/menu'
import Layout from '@/layout/index'

const state = {
  // 路由对象数组，因为我们整个左侧导航中，每个菜单就是一个路由对象，我们把后端获取到的所有菜单对象
  // 封装到router路由对象中，再把每个路由对象存入到routers路由数组里。
  routers: []
}

// 就是存放方法的(类似于组件中的methods)，在这些方法中是可以改变state中定义的数据的值。
// 比如我们想改变state中定义的routers路由对象数组里的值，就可以定义一个方法去改变它。
const mutations = {
  // 实现为state中的routers路由对象数组赋值
  SET_ROUTERS(state, data) {
    // 要想调用到state中定义的数据，方法中需要定义state形参，再使用state.属性名来调用它
    state.routers = data
  },
  RESET_ROUTERS(state) {
    // 重置state中定义的routers数组, 在用户退出登录时需要提交这个方法
    state.routers = []
  }
}

const actions = {
  // 定义一个初始化路由的方法，实现为state中的routers路由对象数组赋值
  initRouters({ commit }) { // data为Vue组件中调用initRouters方法时传入的数据。
    return new Promise((resolve, reject) => {
      // 执行调用@/api/menu.js中的getMenuList()方法，实现后端返回过来的菜单列表数据保存到state中
      getMenuList().then((data) => {
        // 调用完formatRouters()方法将data格式化好的路由对象数组进行返回再赋值给fmtRouters
        const fmtRouters = formatRouters(data)
        // 提交mutations中定义的SET_ROUTERS方法, 将fmtRouters赋值给state中定义的routers
        // fmtRouters为调用[通过用户id查询菜单列表]接口返回的菜单列表数据, List<Menu>
        commit('SET_ROUTERS', fmtRouters)
        // 再将格式化好的路由数组进行返回
        resolve(fmtRouters)
      }).catch((err) => {
        // 使用reject返回错误信息
        reject(err)
      })
    })
  }
}

// formatRouters()方法用于对响应过来的菜单数据(data)进行格式化
const formatRouters = (data) => {
  // data为后端响应过来的List<Menu>菜单列表数据
  const fmtRouters = [] // 定义一个空的路由对象数组
  // 对从后端响应过来的List<Menu>菜单列表数据使用forEach进行循环遍历
  data.forEach(router => {
    // 循环出的每个Menu菜单对象, 从每个菜单对象中取出个别值再赋值给router
    const { path, component, name, iconCls } = router
    let { children } = router
    if (children && children instanceof Array) {
      // 如果children存在(即当前Menu菜单对象下有子菜单对象)，并且它是Array数组类型
      // 使用递归取出当前菜单里的子菜单对象信息
      children = formatRouters(children)
    }
    // 单独对router路由对象中的属性格式化后，挨个赋值给fmtRouter对象
    const fmtRouter = {
      path: path,
      name: name,
      // iconCls: iconCls,
      meta: { icon: iconCls, title: name },
      children: children,
      // component的值在router/index.js路由文件中是一个组件对象，而在t_menu菜单表中component是字符串类型的值
      // 所以我们这里需要将这个字符串类型的值转换成具体某个组件对象，所有自定义组件将创建在views目录中
      component: component === '/Home' ? Layout : require('@/views' + component + '.vue').default
    }
    // 再将格式化好的fmtRouter路由对象添加到fmtRouters路由对象数组中
    fmtRouters.push(fmtRouter)
  })
  // 将查询到的菜单列表(路由对象数组)进行返回
  return fmtRouters
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}
